<?php

/**
 * Pwiff - PHP SWF Library
 *
 * LICENSE
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 *
 * @package    Pwiff
 * @subpackage Records
 * @copyright  Copyright (c) 2010 Steven Harris
 * @license    http://www.opensource.org/licenses/bsd-license.php New BSD License
 * @version    $Id: FillStyle.php 6 2010-02-17 04:28:26Z indigo.sunrise $
 */

/**
 * FillStyle record.
 * 
 * @package    Pwiff
 * @subpackage Records
 */
class Pwiff_Record_FillStyle extends Pwiff_Record
{
	/**#@+
	 * Fill style type constants.
	 *
	 * @var int
	 */
	const SOLID = 0x00;
	
	const GRADIENT_LINEAR = 0x10;
	const GRADIENT_RADIAL = 0x12;
	const GRADIENT_FOCAL  = 0x13;
	
	const BITMAP_REPEATING = 0x40;
	const BITMAP_CLIPPED   = 0x41;
	const BITMAP_REPEATING_NONSMOOTH = 0x42;
	const BITMAP_CLIPPED_NONSMOOTH   = 0x43;
	/**#@-*/
	
	/**
	 * DefineShape version this record is being used with.
	 * 
	 * @var int
	 */
	protected $shapeVersion = 1;
	
	/**
	 * The type of fill style to use.
	 * 
	 * @var int
	 */
	protected $fillType = self::SOLID;
	
	/**
	 * Solid RGB or RGBA (Shape3+) color.
	 * 
	 * @var Pwiff_Record_RGB
	 */
	protected $color = null;
	
	/**
	 * Matrix for the gradient fill.
	 *
	 * @var Pwiff_Record_Matrix
	 */
	protected $gradientMatrix = null;
	
	/**
	 * Gradient or FocalGradient (Shape4+) fill.
	 * 
	 * @var Pwiff_Record_Gradient
	 */
	protected $gradient = null;
	
	/**
	 * Bitmap character ID when using a bitmap fill.
	 * 
	 * @var int
	 */
	protected $bitmapId = 0;
	
	/**
	 * Matrix used for the bitmap fill.
	 * 
	 * @var Pwiff_Record_Matrix
	 */
	protected $bitmapMatrix = null;
	
	/**
	 * Sets the DefineShape version.
	 * 
	 * @param  int $version
	 * @return Pwiff_Record_FillStyle
	 */
	public function setShapeVersion($version)
	{
		$this->shapeVersion = $version;
		return $this;
	}
	
	/**
	 * Sets the fill style type.
	 * 
	 * @param  int $fillType
	 * @return Pwiff_Record_FillStyle
	 */
	public function setFillStyleType($fillType)
	{
		if ($fillType === self::GRADIENT_FOCAL AND $this->shapeVersion < 4) {
			throw new Pwiff_Exception('At least DefineShape4 is required for focal gradients.');
		}
		
		$this->fillType = $fillType;
		return $this;
	}
	
	/**
	 * Sets the RGB or RGBA solid fill color.
	 * 
	 * @param  Pwiff_Record_RGB $color
	 * @return Pwiff_Record_FillStyle
	 */
	public function setColor(Pwiff_Record_RGB $color)
	{
		if ($this->shapeVersion < 3 AND ($color instanceof Pwiff_Record_RGBA)) {
			throw new Pwiff_Exception('At least DefineShape3 is required for RGBA color.');
		}
		
		if ($this->shapeVersion >= 3 AND !($color instanceof Pwiff_Record_RGBA)) {
			throw new Pwiff_Exception('An RGBA color is required for DefineShape3 and higher.');
		}
		
		$this->color = $color;
		return $this;
	}
	
	/**
	 * Sets the gradient fill.
	 *
	 * @param  Pwiff_Record_Gradient $gradient
	 * @return Pwiff_Record_FillStyle
	 */
	public function setGradient(Pwiff_Record_Gradient $gradient)
	{
		if ($this->shapeVersion < 4 AND ($gradient instanceof Pwiff_Record_FocalGradient)) {
			throw new Pwiff_Exception('At least DefineShape4 is required for focal gradients.');
		}
		
		if ($this->fillType === self::GRADIENT_FOCAL
			AND !($gradient instanceof Pwiff_Record_FocalGradient)) {
			throw new Pwiff_Exception('A focal gradient fill type was specified, but the given gradient is not a focal type.');
		}
		
		$this->gradient = $gradient;
		return $this;
	}
	
	/**
	 * Sets the matrix used for the gradient.
	 * 
	 * @param  Pwiff_Record_Matrix $matrix
	 * @return Pwiff_Record_FillStyle
	 */
	public function setGradientMatrix(Pwiff_Record_Matrix $matrix)
	{
		$this->gradientMatrix = $matrix;
		return $this;
	}
	
	/**
	 * Sets the bitmap character ID for bitmap fills.
	 *
	 * @param  int $bitmapId
	 * @return Pwiff_Record_FillStyle
	 */
	public function setBitmapId($bitmapId)
	{
		$this->bitmapId = $bitmapId;
		return $this;
	}
	
	/**
	 * Sets the matrix used for the bitmap.
	 * 
	 * @param  Pwiff_Record_Matrix $matrix
	 * @return Pwiff_Record_FillStyle
	 */
	public function setBitmapMatrix(Pwiff_Record_Matrix $matrix)
	{
		$this->bitmapMatrix = $matrix;
		return $this;
	}
	
	/**
	 * Gets the DefineShape version.
	 * 
	 * @return int
	 */
	public function getShapeVersion()
	{
		return $this->shapeVersion;
	}
	
	/**
	 * Gets the fill style type.
	 * 
	 * @return int
	 */
	public function getFillStyleType()
	{
		return $this->fillType;
	}
	
	/**
	 * Gets the solid fill color.
	 * 
	 * @return Pwiff_Record_RGB
	 */
	public function getColor()
	{
		return $this->color;
	}
	
	/**
	 * Gets the gradient fill.
	 * 
	 * @return Pwiff_Record_Gradient
	 */
	public function getGradient()
	{
		return $this->gradient;
	}
	
	/**
	 * Gets the gradient matrix.
	 * 
	 * @return Pwiff_Record_Matrix
	 */
	public function getGradientMatrix()
	{
		return $this->gradientMatrix;
	}
	
	/**
	 * Gets the bitmap character ID.
	 *
	 * @return int
	 */
	public function getBitmapId()
	{
		return $this->bitmapId;
	}
	
	/**
	 * Gets the bitmap matrix.
	 * 
	 * @return Pwiff_Record_Matrix
	 */
	public function getBitmapMatrix()
	{
		return $this->bitmapMatrix;
	}
	
	/**
	 * Gets the record length.
	 *
	 * @return int
	 */
	public function getRecordLength()
	{
		$length = 1;
		
		// solid fill - add RGB/RGBA record
		if ($this->fillType === self::SOLID) {
			$length += $this->color->getRecordLength();
		}
		// gradient fill - add gradient and matrix records
		else if ($this->fillType >= self::GRADIENT_LINEAR
			AND $this->fillType <= self::GRADIENT_FOCAL) {
			$length += $this->gradient->getRecordLength();
			$length += $this->gradientMatrix->getRecordLength();
		}
		// bitmap fill - add 2 (short) and matrix record
		else if ($this->fillType >= self::BITMAP_REPEATING
			AND $this->fillType <= self::BITMAP_CLIPPED_NONSMOOTH) {
			$length += 2;
			$length += $this->bitmapMatrix->getRecordLength();
		}
		
		return $length;
	}
	
	/**
	 * Writes the FillStyle record to the given output instance.
	 * 
	 * @param  Pwiff_Output $out
	 */
	public function write(Pwiff_Output $out)
	{
		$out->writeUI8($this->fillType);
		
		// solid fill
		if ($this->fillType === self::SOLID) {
			$this->color->write($out);
		}
		// gradient fill
		else if ($this->fillType >= self::GRADIENT_LINEAR
			AND $this->fillType <= self::GRADIENT_FOCAL) {
			$this->gradient->write($out);
			$this->gradientMatrix->write($out);
		}
		// bitmap fill
		else if ($this->fillType >= self::BITMAP_REPEATING
			AND $this->fillType <= self::BITMAP_CLIPPED_NONSMOOTH) {
			$out->writeUI16($this->bitmapId);
			$this->bitmapMatrix->write($out);
		}
	}
}
